package com.agileai.hotweb.common;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;

public class BeanBuilder {
	
	private List<String> excludePropertys = new ArrayList<String>();
	private Hashtable<String,String> propertyMapper = new Hashtable<String,String>();
	private Hashtable<String,String> valueContainer = new Hashtable<String,String>();
	
	@SuppressWarnings("rawtypes")
	private HashMap dataMap = null;
	@SuppressWarnings("rawtypes")
	private List<HashMap> dataMapList = null;
	@SuppressWarnings("rawtypes")
	private Class beanClazz = null;
	private Object beanInstance = null;
	private List<Object> beanInstList = new ArrayList<Object>();
	
	private boolean isMulti = false;
	
	@SuppressWarnings("rawtypes")
	public BeanBuilder(Object beanInstance,HashMap dataMap){
		this.beanInstance = beanInstance;
		this.dataMap = dataMap;
		this.isMulti = false;
	}	
	@SuppressWarnings("rawtypes")
	public BeanBuilder(Class beanClazz,HashMap dataMap){
		this.beanClazz = beanClazz;
		this.dataMap = dataMap;
		this.isMulti = false;
	}
	@SuppressWarnings("rawtypes")
	public BeanBuilder(Class beanClazz,List<HashMap> dataMapList){
		this.beanClazz = beanClazz;
		this.dataMapList = dataMapList;
		this.isMulti = true;
	}
	public BeanBuilder bind(String property,String fieldName){
		propertyMapper.put(property, fieldName);
		return this;
	}

	public BeanBuilder addExcludeProperty(String property){
		this.excludePropertys.add(property);
		return this;
	}
	@SuppressWarnings("rawtypes")
	private HashMap getBeanMap(HashMap dataMap){
		HashMap<String,Object> result = new HashMap<String,Object>();
		try {
			for (Enumeration en = propertyMapper.keys();en.hasMoreElements();){
				String beanProperty = (String)en.nextElement();
				if (this.excludePropertys.contains(beanProperty))continue;
				String fieldName = propertyMapper.get(beanProperty);
				Object beanPropertyValue = dataMap.get(fieldName);
				result.put(beanProperty, beanPropertyValue);
			}
			for (Enumeration en = valueContainer.keys();en.hasMoreElements();){
				String beanProperty = (String)en.nextElement();
				if (this.excludePropertys.contains(beanProperty))continue;
				String beanPropertyValue = valueContainer.get(beanProperty);
				result.put(beanProperty, beanPropertyValue);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}
	public Object getBean(){
		Object result = null;
		try {
			this.pack();
			result = this.beanInstance;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}
	public List<Object> getBeanList(){
		List<Object> result = null;;
		try {
			this.pack();
			return this.beanInstList;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	@SuppressWarnings("rawtypes")
	public void pack() {
		try {
			if (this.isMulti){
				for (int i=0;i < this.dataMapList.size();i++){
					Object beanInstance = this.beanClazz.newInstance();
					HashMap dataMap = this.dataMapList.get(i);
					Map properties = this.getBeanMap(dataMap);
					ConvertUtils.register(new DateConvert(),java.util.Date.class);
					ConvertUtils.register(new SetConvert(),java.util.Set.class);
					BeanUtilsBean.getInstance().populate(beanInstance, properties);
					this.beanInstList.add(beanInstance);
				}
			}else{
				if (this.beanInstance == null){
					this.beanInstance = this.beanClazz.newInstance();
				}
				Map properties = this.getBeanMap(this.dataMap);
				ConvertUtils.register(new DateConvert(),java.util.Date.class);
				ConvertUtils.register(new SetConvert(),java.util.Set.class);
				BeanUtilsBean.getInstance().populate(this.beanInstance, properties);				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
class DateConvert implements Converter{
	private static final String  SPLIT = "/";
	@SuppressWarnings("rawtypes")
	public Object convert(Class clazz, Object datetime) {   
        String dateValue = String.valueOf(datetime).trim();   
        if(dateValue.equals("null")|| dateValue.trim().length()==0){   
            return null;
        }   
        try{
        	String[] format8value = this.getFormate8value(dateValue);
            SimpleDateFormat df = new SimpleDateFormat(format8value[1]);
            return df.parse(format8value[0]);   
        }   
        catch(Exception e){   
            return null;   
        }   
    }
    private String[] getFormate8value(String dateTime){
    	String[] result = new String[2];
        switch (dateTime.length()) {
        case 10:
            result[0] = dateTime.substring(0, 4) + SPLIT + dateTime.substring(5, 7) + SPLIT + dateTime.substring(8, 10); 
            result[1] = "yyyy/MM/dd";
            break;
        case 16:
        	result[0] = dateTime.substring(0, 4) + SPLIT + dateTime.substring(5, 7) + SPLIT + dateTime.substring(8, 10)
        		+ " " + dateTime.substring(11,13)+ ":"+dateTime.substring(14,16);
        	result[1] = "yyyy/MM/dd HH:mm";
            break;
        case 19:
        	result[0] = dateTime.substring(0, 4) + SPLIT + dateTime.substring(5, 7) + SPLIT + dateTime.substring(8, 10)
    		+ " " + dateTime.substring(11,13)+ ":"+dateTime.substring(14,16)+":"+dateTime.substring(17,19);
            result[1] = "yyyy/MM/dd HH:mm:ss";
            break;
        default:
            result[0] = dateTime.substring(0, 4) + SPLIT + dateTime.substring(5, 7) + SPLIT + dateTime.substring(8, 10); 
        	result[1] = "yyyy/MM/dd";
            break;
        }
        return result;
    }
}
class SetConvert implements Converter{
	@SuppressWarnings("rawtypes")
	public Object convert(Class clazz, Object datetime) {   
		return null;
    }
}
